package com.itgacl.magic4j.libcommon.component.lock;

import com.itgacl.magic4j.libcommon.component.lock.util.LockUtil;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.Assert;


/**
 * 锁模板方法
 *
 */
@Slf4j
public class LockTemplate {

    private static final String PROCESS_ID = LockUtil.getLocalMAC() + LockUtil.getJvmPid();

    @Setter
    private LockExecutor lockExecutor;

    /**
     * 加锁
     * @param key
     * @param expire
     * @param timeout
     * @return
     * @throws Exception
     */
    public LockInfo lock(String key, long expire, long timeout) throws Exception {
        Assert.isTrue(timeout > 0, "tryTimeout must more than 0");
        long start = System.currentTimeMillis();
        int acquireCount = 0;
        String value = PROCESS_ID + Thread.currentThread().getId();
        while (System.currentTimeMillis() - start < timeout) {
            boolean result = lockExecutor.acquire(key, value, expire);
            acquireCount++;
            if (result) {
                LockInfo lockInfo = new LockInfo(key, value, expire, timeout, acquireCount);
                log.debug(Thread.currentThread().getName()+"获取到分布式锁：{}",lockInfo);
                return lockInfo;
            }
            Thread.sleep(50);
        }
        log.info(Thread.currentThread().getName()+"获取 lock failed, try {} times", acquireCount);
        return null;
    }

    /**
     * 释放锁
     * @param lockInfo
     * @return
     */
    public boolean releaseLock(LockInfo lockInfo) {
        log.debug(Thread.currentThread().getName()+"释放分布式锁：{}",lockInfo);
        return lockExecutor.releaseLock(lockInfo);
    }
}
